package com.enjoyor.soa.traffic.core.efoms.service.impl;

import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.apache.commons.lang3.StringUtils;
import org.easyrules.api.RulesEngine;
import org.easyrules.core.RulesEngineBuilder;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import com.alibaba.fastjson.JSONArray;
import com.enjoyor.soa.traffic.core.efoms.domain.DeviceStatusInfo;
import com.enjoyor.soa.traffic.core.efoms.domain.FileInfo;
import com.enjoyor.soa.traffic.core.efoms.domain.RepairsInfo;
import com.enjoyor.soa.traffic.core.efoms.domain.RepairsRecordInfo;
import com.enjoyor.soa.traffic.core.efoms.easyrule.AuditRecordRule;
import com.enjoyor.soa.traffic.core.efoms.easyrule.CancelRecordRule;
import com.enjoyor.soa.traffic.core.efoms.easyrule.PressRecordRule;
import com.enjoyor.soa.traffic.core.efoms.enums.EnumDicPublic;
import com.enjoyor.soa.traffic.core.efoms.enums.EnumMessage;
import com.enjoyor.soa.traffic.core.efoms.mapper.IDeviceStatusInfoMapper;
import com.enjoyor.soa.traffic.core.efoms.mapper.IFileInfoMapper;
import com.enjoyor.soa.traffic.core.efoms.mapper.IRepairsInfoMapper;
import com.enjoyor.soa.traffic.core.efoms.mapper.IRepairsRecordInfoMapper;
import com.enjoyor.soa.traffic.core.efoms.service.IRepairsInfoService;
import com.enjoyor.soa.traffic.frame.logger.IPubLogMapper;
import com.enjoyor.soa.traffic.util.enums.EnumAppCode;
import com.enjoyor.soa.traffic.util.enums.log.LogInfoDic;
import com.enjoyor.soa.traffic.util.helper.LoggerHelper;
import com.enjoyor.soa.traffic.util.helper.ResultHelper;
import com.enjoyor.soa.traffic.util.helper.TimeHelper;
import com.enjoyor.soa.traffic.util.pojo.Page;
import com.enjoyor.soa.traffic.util.pojo.ResultPojo;

@Service
@Transactional
@SuppressWarnings("rawtypes")
public class RepairsInfoService implements IRepairsInfoService {

	@Autowired
	private IPubLogMapper pubLogMapper;

	@Autowired
	private IRepairsInfoMapper repairsInfoMapper;

	@Autowired
	private IDeviceStatusInfoMapper deviceStatusInfoMapper;

	@Autowired
	private IRepairsRecordInfoMapper repairsRecordInfoMapper;

	@Autowired
	private IFileInfoMapper fileInfoMapper;

	@Override
	public RepairsInfo select(String repairsId) {
		// TODO Auto-generated method stub
		Map<String, List> recordListMap = this.getRepOperRecord(repairsId);
		RepairsInfo repairsInfo = repairsInfoMapper.selectById(repairsId);
		if (repairsInfo != null) {
			repairsInfo.setRecordMap(recordListMap);
			Map<String, Object> fileMap = new HashMap<>();
			List<FileInfo> fileList = fileInfoMapper.getFileListByReleteId(repairsId);
			repairsInfo.setFileList(fileList);
		}
		return repairsInfo;
	}

	@Override
	public List<RepairsInfo> selectList(String repairsId, String repStatusCode, String devTypeCode, String devAreaCode,
			String devId, String devName, String key, String press, String repDeptIds, String startTime,
			String endTime) {
		// TODO Auto-generated method stub
		Map<String, Object> paramT = this.getRepSelectMap(repairsId, repStatusCode, devTypeCode, devAreaCode, devId,
				devName, key, press, repDeptIds, startTime, endTime);
		return repairsInfoMapper.selectRepairsInfoList(paramT);
	}

	@Override
	public Page selectPage(Page page, String repairsId, String repStatusCode, String devTypeCode, String devAreaCode,
			String key, String press, String repDeptIds, String startTime, String endTime) {
		// TODO Auto-generated method stub
		Map<String, Object> paramT = this.getRepSelectMap(repairsId, repStatusCode, devTypeCode, devAreaCode, null,
				null, key, press, repDeptIds, startTime, endTime);
		page.setMapBean(paramT);
		return repairsInfoMapper.selectRepairsInfoPage(page);
	}

	@Override
	public ResultPojo insert(RepairsInfo repairsInfo, String userName) {
		// TODO Auto-generated method stub
		RepairsInfo addRepairsInfo = this.getRepairsInfo(repairsInfo, userName);
		try {
			List<FileInfo> fileInfoList = repairsInfo.getFileList();
			DeviceStatusInfo deviceStatusInfo = this.getDevStatusInfo(repairsInfo.getDevId());
			this.repairsInfoMapper.insertSelective(addRepairsInfo);
			this.insertFileList(fileInfoList, repairsInfo.getRepairsId());
			this.deviceStatusInfoMapper.updateDevStatusInfo(deviceStatusInfo);
			pubLogMapper.saveNoramlLogInfo(userName, null, LogInfoDic.LOG_TRANSTYPE_ENUM.TRANSTYPE_INSERT.getCode(),
					String.format("添加报修单编号:{%s} 操作成功!", new Object[] { repairsInfo.getId() }),
					LogInfoDic.LOG_MODULAR_ENUM.EFOMS_REPAIRS_MANAGEMENT.getMessage());
			return ResultHelper.getResult(addRepairsInfo.getRepairsId());
		} catch (Exception e) {
			// TODO: handle exception
			LoggerHelper.LOG.error(e);
			throw e;
		}
	}

	@Override
	public ResultPojo edit(RepairsInfo repairsInfo, String userName) {
		// TODO Auto-generated method stub
		repairsInfo.setUpdateDate(TimeHelper.dateToLongString());
		try {
			List<FileInfo> fileInfoList = repairsInfo.getFileList();
			this.repairsInfoMapper.updateByIdSelective(repairsInfo);
			this.fileInfoMapper.deleteFileByReleteId(repairsInfo.getRepairsId());
			this.insertFileList(fileInfoList, userName);
			pubLogMapper.saveNoramlLogInfo(userName, null, LogInfoDic.LOG_TRANSTYPE_ENUM.TRANSTYPE_UPDATE.getCode(),
					String.format("修改报修单表单编号:{%s} 操作成功!", new Object[] { repairsInfo.getId() }),
					LogInfoDic.LOG_MODULAR_ENUM.EFOMS_REPAIRS_MANAGEMENT.getMessage());
			return ResultHelper.getResult(repairsInfo.getRepairsId());
		} catch (Exception e) {
			LoggerHelper.LOG.error(e);
			throw e;
		}
	}

	@Override
	public ResultPojo delete(String repairsId, String userName) {
		try {
			if (this.checkRepairInfo(repairsId) != null) {
				this.repairsInfoMapper.deleteById(repairsId);
				pubLogMapper.saveNoramlLogInfo(userName, null, LogInfoDic.LOG_TRANSTYPE_ENUM.TRANSTYPE_UPDATE.getCode(),
						String.format("删除报修单表单编号:{%s} 操作成功!", new Object[] { repairsId }),
						LogInfoDic.LOG_MODULAR_ENUM.EFOMS_REPAIRS_MANAGEMENT.getMessage());
				return ResultHelper.getResult(repairsId);
			} else {
				return ResultHelper.getResult(EnumAppCode.ERROR_NO_EXIST_REPAIRID);
			}
		} catch (Exception e) {
			LoggerHelper.LOG.error(e);
			throw e;
		}
	}

	@Override
	public ResultPojo audit(String repairsId, String userName, String isPass, String operExplain) {
		RepairsInfo repairsInfo = this.getAuditRepInfo(repairsId, isPass);
		RepairsRecordInfo repairsRecordInfo = this.getRepairsRecordInfo("AUDIT", operExplain, userName, repairsId);
		// 判断审核是否审核通过；
		try {
			if (this.checkRepairInfo(repairsId) != null) {
				this.repairsInfoMapper.updateByIdSelective(repairsInfo);
				this.repairsRecordInfoMapper.insertSelective(repairsRecordInfo);
				pubLogMapper.saveNoramlLogInfo(userName, null, LogInfoDic.LOG_TRANSTYPE_ENUM.TRANSTYPE_UPDATE.getCode(),
						String.format("报修单审核表单编号:{%s} 操作成功!", new Object[] { repairsInfo.getId() }),
						LogInfoDic.LOG_MODULAR_ENUM.EFOMS_REPAIRS_MANAGEMENT.getMessage());
				return ResultHelper.getResult(repairsId);
			} else {
				return ResultHelper.getResult(EnumAppCode.ERROR_NO_EXIST_REPAIRID);
			}
		} catch (Exception e) {
			LoggerHelper.LOG.error(e);
			throw e;
		}
	}

	@Override
	public ResultPojo cancel(String repairsId, String userName, String operExplain, String operReasonCode,
			String operReasonName) {
		RepairsInfo repairsInfo = this.getCancelRepInfo(repairsId);
		if (this.checkRepairInfo(repairsId) != null) {
			try {
				RepairsRecordInfo repairsRecordInfo = this.getRepairsRecordInfo("CANCEL", operExplain, userName,
						repairsId);
				this.repairsInfoMapper.updateByIdSelective(repairsInfo);
				this.repairsRecordInfoMapper.insertSelective(repairsRecordInfo);
				pubLogMapper.saveNoramlLogInfo(userName, null, LogInfoDic.LOG_TRANSTYPE_ENUM.TRANSTYPE_UPDATE.getCode(),
						String.format("报修单撤销表单编号:{%s} 操作成功!", new Object[] { repairsInfo.getId() }),
						LogInfoDic.LOG_MODULAR_ENUM.EFOMS_REPAIRS_MANAGEMENT.getMessage());
				return ResultHelper.getResult(repairsId);
			} catch (Exception e) {
				LoggerHelper.LOG.error(e);
				throw e;
			}
		} else {
			return ResultHelper.getResult(EnumAppCode.ERROR_NO_EXIST_REPAIRID);
		}
	}

	@Override
	public ResultPojo press(String repairsId, String userName, String operExplain) {
		RepairsInfo repairsInfo = this.checkRepairInfo(repairsId);
		RepairsRecordInfo repairsRecordInfo = this.getRepairsRecordInfo("PRESS", operExplain, userName, repairsId);
		int pressTimes = repairsInfo.getPressTimes() + 1;
		repairsInfo.setPressTimes(pressTimes);
		if (repairsInfo != null) {
			try {
				this.repairsInfoMapper.updateByIdSelective(repairsInfo);
				this.repairsRecordInfoMapper.insertSelective(repairsRecordInfo);
				pubLogMapper.saveNoramlLogInfo(userName, null, LogInfoDic.LOG_TRANSTYPE_ENUM.TRANSTYPE_UPDATE.getCode(),
						String.format("报修单催办表单编号:{%s} 操作成功!", new Object[] { repairsInfo.getId() }),
						LogInfoDic.LOG_MODULAR_ENUM.EFOMS_REPAIRS_MANAGEMENT.getMessage());
				return ResultHelper.getResult(repairsInfo.getRepairsId());
			} catch (Exception e) {
				LoggerHelper.LOG.error(e);
				throw e;
			}
		} else {
			return ResultHelper.getResult(EnumAppCode.ERROR_NO_EXIST_REPAIRID);
		}
	}

	/**
	 * 获取所有操作信息计数
	 *
	 * @return
	 */
	@Override
	public Map<String, Object> getOperationCount(String startTime, String endTime) {
		Map<String, Object> map = new HashMap<>();
		int apply = repairsInfoMapper.countApplyRepairsInfo(startTime, endTime);
		int press = repairsInfoMapper.countRepPressInfo(startTime, endTime);
		// 报修申请
		map.put(EnumMessage.REP_MSG_APPLY.getKey(), apply);
		// 催办
		map.put(EnumMessage.REP_MSG_PRESS.getKey(), press);
		return map;
	}

	@Override
	public int countApplyRepairsInfo(String startTime, String endTime) {
		return repairsInfoMapper.countApplyRepairsInfo(startTime, endTime);
	}

	@Override
	public int countRepPressInfo(String startTime, String endTime) {
		return repairsInfoMapper.countRepPressInfo(startTime, endTime);
	}

	/**
	 * 校验对象是否存在；
	 * 
	 * @param repairsId
	 *            报修单编号；
	 * @return RepairsInfo
	 */
	private RepairsInfo checkRepairInfo(String repairsId) {
		RepairsInfo checkRepairs = repairsInfoMapper.selectById(repairsId);
		if (null != checkRepairs) {
			return checkRepairs;
		} else {
			return null;
		}
	}

	/**
	 * 获取操作记录；
	 * 
	 * @param repairsId
	 * @return Map
	 */
	private Map<String, List> getRepOperRecord(String repairsId) {
		Map<String, Object> recordMap = new HashMap<String, Object>();
		recordMap.put("repairsId", repairsId);
		List<RepairsRecordInfo> recordList = repairsRecordInfoMapper.selectRepairsRecodeInfoList(recordMap);
		Map<String, List> recordListMap = new HashMap<String, List>();
		List cancelList = new ArrayList<>(); // 撤销List；
		List auditList = new ArrayList<>(); // 审核List;
		List pressList = new ArrayList<>(); // 催办List；
		RulesEngine fizzBuzzEngine = RulesEngineBuilder.aNewRulesEngine().withSkipOnFirstAppliedRule(true)
				.withSilentMode(true).build();
		// 声明审核通过规则；
		PressRecordRule pressRecordRule = new PressRecordRule();
		CancelRecordRule CancelRecordRule = new CancelRecordRule();
		AuditRecordRule AuditRecordRule = new AuditRecordRule();
		// 注册规则；
		fizzBuzzEngine.registerRule(pressRecordRule);
		fizzBuzzEngine.registerRule(CancelRecordRule);
		fizzBuzzEngine.registerRule(AuditRecordRule);
		// 参数设置；
		for (int i = 0; i < recordList.size(); i++) {
			pressRecordRule.setCode(recordList.get(i).getOperTypeCode());
			pressRecordRule.setRepairsRecordInfo(recordList.get(i));
			pressRecordRule.setList(pressList);

			CancelRecordRule.setCode(recordList.get(i).getOperTypeCode());
			CancelRecordRule.setRepairsRecordInfo(recordList.get(i));
			CancelRecordRule.setList(cancelList);

			AuditRecordRule.setCode(recordList.get(i).getOperTypeCode());
			AuditRecordRule.setRepairsRecordInfo(recordList.get(i));
			AuditRecordRule.setList(auditList);
			fizzBuzzEngine.fireRules();
		}
		recordListMap.put("pressList", pressList);
		recordListMap.put("cancelList", cancelList);
		recordListMap.put("auditList", auditList);
		return recordListMap;
	}

	/**
	 * 获取报修单查询条件；
	 */
	private Map<String, Object> getRepSelectMap(String repairsId, String repStatusCode, String devTypeCode,
			String devAreaCode, String devId, String devName, String key, String press, String repDeptIds,
			String startTime, String endTime) {
		Map<String, Object> paramT = new HashMap<String, Object>();
		List deptList = JSONArray.parseArray(repDeptIds, String.class);
		paramT.put("repairsId", repairsId);
		paramT.put("repStatusCode", repStatusCode);
		paramT.put("devTypeCode", devTypeCode);
		paramT.put("devAreaCode", devAreaCode);
		paramT.put("devId", devId);
		paramT.put("devName", devName);
		paramT.put("key", key);
		paramT.put("repDeptIds", deptList);
		paramT.put("startTime", startTime);
		paramT.put("endTime", endTime);
		paramT.put("press", press);
		return paramT;
	}

	/**
	 * 获取审核信息对象；
	 * 
	 * @param repairsId
	 * @param isPass
	 * @return
	 */
	private RepairsInfo getAuditRepInfo(String repairsId, String isPass) {
		RepairsInfo repairsInfo = new RepairsInfo();
		repairsInfo.setRepairsId(repairsId);
		repairsInfo.setUpdateDate(TimeHelper.dateToLongString());
		if (!StringUtils.isBlank(isPass) && isPass.equals("1")) {
			repairsInfo.setRepStatusCode(EnumDicPublic.REP_CHECKPASS.getKey());
			repairsInfo.setRepStatusName(EnumDicPublic.REP_CHECKPASS.getValue());
		} else if (!StringUtils.isBlank(isPass) && isPass.equals("0")) {
			repairsInfo.setRepStatusCode(EnumDicPublic.REP_CHECKREJECT.getKey());
			repairsInfo.setRepStatusName(EnumDicPublic.REP_CHECKREJECT.getValue());
		}
		return repairsInfo;
	}

	/**
	 * 批量插入文件
	 * 
	 * @param fileInfoList：文件集合；
	 * @param RepairsId：报修单编号；
	 */
	private void insertFileList(List<FileInfo> fileInfoList, String RepairsId) {
		for (FileInfo fileInfo : fileInfoList) {
			String fileId = "F" + TimeHelper.getUniqueString();
			fileInfo.setFileId(fileId);
			fileInfo.setReleteId(RepairsId);
			fileInfoMapper.insert(fileInfo);
		}
	}

	/**
	 * get设备状态pojo(用于报修单生成之后改变设备状态)
	 * 
	 * @param devId：设备编号；
	 * @return DeviceStatusInfo;
	 */
	private DeviceStatusInfo getDevStatusInfo(String devId) {
		DeviceStatusInfo deviceStatusInfo = new DeviceStatusInfo();
		deviceStatusInfo.setDevId(devId);
		deviceStatusInfo.setDevStatusCode(EnumDicPublic.DEVICE_STATUS_FAILURE.getKey());
		deviceStatusInfo.setDevStatusName(EnumDicPublic.DEVICE_STATUS_FAILURE.getValue());
		return deviceStatusInfo;
	}

	/**
	 * 获取报修单添加对象信息；
	 * 
	 * @param repairsInfo：报修单对象；
	 * @param userName
	 *            ：用户名；
	 * @return RepairsInfo;
	 */
	private RepairsInfo getRepairsInfo(RepairsInfo repairsInfo, String userName) {
		String repairsId = "R" + TimeHelper.getUniqueString();
		String systemDate = TimeHelper.dateToLongString();
		repairsInfo.setRepairsId(repairsId);
		repairsInfo.setRepDate(systemDate);
		repairsInfo.setUpdateDate(systemDate);
		//repairsInfo.setRepPersonName(userName);
		repairsInfo.setPressTimes(0);
		repairsInfo.setRepStatusCode(EnumDicPublic.REP_WAITCHECK.getKey());
		repairsInfo.setRepStatusName(EnumDicPublic.REP_WAITCHECK.getValue());
		return repairsInfo;
	}

	/**
	 * 报修单操作记录对象生成；
	 * 
	 * @param Flag：
	 *            判断是什么操作；
	 * @param operExplain
	 *            ：操作说明；
	 * @param userName：用户名；
	 * @param repairsId
	 *            ：报修单编号；
	 * @return RepairsRecordInfo；
	 */
	private RepairsRecordInfo getRepairsRecordInfo(String Flag, String operExplain, String userName, String repairsId) {
		RepairsRecordInfo repairsRecordInfo = new RepairsRecordInfo();
		if (Flag.equals("AUDIT")) {
			repairsRecordInfo.setRepRecordId(TimeHelper.getUniqueString());
			repairsRecordInfo.setOperateDate(TimeHelper.dateToLongString());
			repairsRecordInfo.setOperExplain(operExplain);
			repairsRecordInfo.setOperPerson(userName);
			repairsRecordInfo.setOperReasonCode(EnumDicPublic.REP_CHECKPASS.getKey());
			repairsRecordInfo.setOperReasonName(EnumDicPublic.REP_CHECKPASS.getValue());
			repairsRecordInfo.setOperTypeCode(EnumDicPublic.REP_OPER_CHECK.getKey());
			repairsRecordInfo.setOperTypeName(EnumDicPublic.REP_OPER_CHECK.getValue());
			repairsRecordInfo.setOperResultCode(EnumDicPublic.OPER_CHECKPASS.getKey());
			repairsRecordInfo.setOperResult(EnumDicPublic.OPER_CHECKPASS.getValue());
			repairsRecordInfo.setRepairsId(repairsId);
		} else if (Flag.equals("CANCEL")) {
			repairsRecordInfo.setRepRecordId(TimeHelper.getUniqueString());
			repairsRecordInfo.setOperateDate(TimeHelper.dateToLongString());
			repairsRecordInfo.setOperExplain(operExplain);
			repairsRecordInfo.setOperPerson(userName);
			repairsRecordInfo.setOperReasonCode(EnumDicPublic.REP_CHECKPASS.getKey());
			repairsRecordInfo.setOperReasonName(EnumDicPublic.REP_CHECKPASS.getValue());
			repairsRecordInfo.setOperTypeCode(EnumDicPublic.REP_OPER_DELETE.getKey());
			repairsRecordInfo.setOperTypeName(EnumDicPublic.REP_OPER_DELETE.getValue());
			repairsRecordInfo.setRepairsId(repairsId);
		} else if (Flag.equals("PRESS")) {
			repairsRecordInfo.setRepRecordId(TimeHelper.getUniqueString());
			repairsRecordInfo.setOperateDate(TimeHelper.dateToLongString());
			repairsRecordInfo.setOperExplain(operExplain);
			repairsRecordInfo.setOperPerson(userName);
			repairsRecordInfo.setOperTypeCode(EnumDicPublic.REP_OPER_PRESS.getKey());
			repairsRecordInfo.setOperTypeName(EnumDicPublic.REP_OPER_PRESS.getValue());
			repairsRecordInfo.setRepairsId(repairsId);
		}
		return repairsRecordInfo;
	}

	/**
	 * 获取报修单撤销对象信息；
	 * 
	 * @param repairsId：报修单编号；
	 * @return RepairsInfo；
	 */
	private RepairsInfo getCancelRepInfo(String repairsId) {
		RepairsInfo repairsInfo = new RepairsInfo();
		repairsInfo.setRepairsId(repairsId);
		repairsInfo.setRepStatusCode(EnumDicPublic.REP_ISDELETE.getKey());
		repairsInfo.setRepStatusName(EnumDicPublic.REP_ISDELETE.getValue());
		repairsInfo.setUpdateDate(TimeHelper.dateToLongString());
		return repairsInfo;
	}

}
